#include "Mutex.hpp"
#include <unistd.h>
using namespace wxd;

// class ThreadData
// {
//     public:
//     ThreadData(const std::string& name,Mutex* mutex)
//     :_name(name),_mutex(mutex)
//     {}

//     std::string _name;//线程的名字
//     Mutex* _mutex;
// };

// // 创建自己封装的锁来解决问题
// int ticket = 1000;
// void *route(void *args)
// {
//     ThreadData* data = static_cast<ThreadData*>(args);
//     while (1)
//     {
//         // 加锁-力度尽可能的要精细，不包含过多临界区代码
//         data->_mutex->lock();
//         if (ticket > 0)
//         {
//             usleep(1000);
//             printf("%s sells ticket:%d\n", data->_name.c_str(),ticket);
//             ticket--;
//             data->_mutex->unlock();
//         }
//         else
//         {
//             data->_mutex->unlock();
//             break;
//         }
//     }
//     return nullptr;
// }

// int main(void)
// {

//     // 创建锁
//     Mutex* mutex = new Mutex();

//     //创建4个数据包
//     ThreadData* td1 = new ThreadData("pthread-1",mutex);
//     ThreadData* td2 = new ThreadData("pthread-2",mutex);
//     ThreadData* td3 = new ThreadData("pthread-3",mutex);
//     ThreadData* td4 = new ThreadData("pthread-4",mutex);

//     // 传入锁给线程
//     pthread_t t1, t2, t3, t4;
//     pthread_create(&t1, nullptr, route, td1);
//     pthread_create(&t2, nullptr, route, td2);
//     pthread_create(&t3, nullptr, route, td3);
//     pthread_create(&t4, nullptr, route, td4);

//     pthread_join(t1, nullptr);
//     pthread_join(t2, nullptr);
//     pthread_join(t3, nullptr);
//     pthread_join(t4, nullptr);
// }

class ThreadData
{
public:
    ThreadData(const std::string &name, Mutex *mutex)
        : _name(name), _mutex(mutex)
    {
    }

    std::string _name; // 线程的名字
    Mutex *_mutex;
};

// 创建自己封装的锁来解决问题
int ticket = 1000;
void *route(void *args)
{
    ThreadData *data = static_cast<ThreadData *>(args);
    while (1)
    {
        // 加锁-力度尽可能的要精细，不包含过多临界区代码
        // 直接创建一个局部的LockGuard对象--自动加锁
        // 代码块直接结束自动释放LockGuard对象--自动解锁
        // RAII风格的互斥锁的实现
        {
            LockGuard lock_guard(data->_mutex);
            if (ticket > 0)
            {
                usleep(1000);
                printf("%s sells ticket:%d\n", data->_name.c_str(), ticket);
                ticket--;
            }
            else
            {
                break;
            }
        }
        //休眠一下下，让其他线程有更多机会，看一下结果是否更平均
        usleep(100);
    }
    return nullptr;
}

int main(void)
{

    // 创建锁
    Mutex *mutex = new Mutex();

    // 创建4个数据包
    ThreadData *td1 = new ThreadData("pthread-1", mutex);
    ThreadData *td2 = new ThreadData("pthread-2", mutex);
    ThreadData *td3 = new ThreadData("pthread-3", mutex);
    ThreadData *td4 = new ThreadData("pthread-4", mutex);

    // 传入锁给线程
    pthread_t t1, t2, t3, t4;
    pthread_create(&t1, nullptr, route, td1);
    pthread_create(&t2, nullptr, route, td2);
    pthread_create(&t3, nullptr, route, td3);
    pthread_create(&t4, nullptr, route, td4);

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);
}
